#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/types.h>
#include <fcntl.h>
#include <imp/imp_log.h>

#define TAG "ENV Management"

static pthread_mutex_t mutex;

static void env_lock()
{
	static int lock_init = 0;
	if(lock_init == 0) {
		pthread_mutex_init(&mutex, NULL);
		lock_init = 1;
	}
	pthread_mutex_lock(&mutex);
}

static void env_unlock()
{
	pthread_mutex_unlock(&mutex);
}

/**
 * file data type:
 *	[token1]
 *	parameter1=value1
 *	parameter2=value2
 *	[token2]
 *	parameter1=value1
 *	parameter2=value2
 *
 * input:
 *	@filename:env name
 *	@token:env token
 *	@parameter:parameter in token
 *	@value:return value, parameter value
 *
 * output:
 *	value length(char *)
 */
int read_env(const char *src, const char *token, const char *parameter, char *value)
{
	int ret = 0;

	char token_buffer[100] = "";
	char *file_buffer = NULL;
	char *temp_buffer = NULL;
	char *temp_start_p = NULL;
	char *temp_end_p = NULL;
	char *parameter_p = NULL;

	env_lock();

	file_buffer = (char *)src;
	if( file_buffer == NULL ) {
		IMP_LOG_ERR(TAG, "ERROR: file buffer malloc failed\n");
		ret = -1;
		goto read_out;
	}

	/* find the token in file_buffer and copy to temp_buffer*/
	sprintf(token_buffer, "%s]", token);
	temp_start_p = strstr(file_buffer, token_buffer);
	if( temp_start_p == NULL ) {
		IMP_LOG_ERR(TAG, "ERROR: serch the %s token failed\n", token);
		ret = -1;
		goto file_read_out;
	}

	temp_end_p = strchr(temp_start_p, '[');
	if( temp_end_p == NULL ) {
		temp_buffer = (char *)malloc(strlen(temp_start_p)+1);
		if( temp_buffer == NULL ) {
			IMP_LOG_ERR(TAG, "ERROR: temp_buffer malloc failed %s, %d\n", __func__, __LINE__);
			ret = -1;
			goto file_read_out;
		}
		memset(temp_buffer, 0x00, strlen(temp_start_p)+1);
		strcpy(temp_buffer, temp_start_p);
	} else {
		temp_buffer = (char *)malloc(temp_end_p-temp_start_p+1);
		if( temp_buffer == NULL ) {
			IMP_LOG_ERR(TAG, "ERROR: temp_buffer malloc failed %s, %d\n", __func__, __LINE__);
			ret = -1;
			goto file_read_out;
		}
		memset(temp_buffer, 0x00, temp_end_p-temp_start_p+1);
		strncpy(temp_buffer, temp_start_p, temp_end_p-temp_start_p);
	}

	/* find the parameter in temp_buffer */
	while(1) {
		/* if find but don't parameter we need, continue search */
		if (parameter_p != NULL)
			parameter_p = strstr(parameter_p+strlen(parameter), parameter);
		else /* first serch */
			parameter_p = strstr(temp_buffer, parameter);

		/* not find */
		if( parameter_p == NULL ) {
			//printf("ERROR: no %s this parameter in %s file\n", parameter, filename);
			ret = -1;
			goto temp_read_out;
		}

		/* find but don't we need */
		if( *(parameter_p + strlen(parameter)) != '=' )
			continue;
		else /* already find */
			break;
	}

	/* get the parameter value */
	parameter_p = strchr(parameter_p, '=');
	if( parameter_p == NULL ) {
		IMP_LOG_ERR(TAG, "ERROR: %s parameter no value\n", parameter);
		ret = -1;
		goto temp_read_out;
	}
	strtok(parameter_p, ";");

	/* copy the parameter value to return (char *value) */
	strcpy(value, parameter_p+1);
	ret = strlen(value);
temp_read_out:
	free(temp_buffer);
file_read_out:
read_out:

	env_unlock();
	return ret;
}

/**
 *           temp_start_p                       temp_end_p
 *                |                                  |
 *  -------------------------------------------------------------- file_buffer
 *                |   parameter_p    parameter_end_p |
 *                |       |                  |       |
 *                ------------------------------------             temp_buffer
 *                        |------------------|					   parameter_buffer
 */
int write_env(char *dst, int dst_size, char *token, char *parameter, char *value)
{
	int ret = 0;

	char token_buffer[100] = "";
	char file_buffer[1024] = "";
	char *temp_buffer = NULL;
	char *temp_start_p = NULL;
	char *temp_end_p = NULL;
	char *parameter_p = NULL;
	char *parameter_end_p = NULL;
	char *parameter_buffer = (char *)malloc(256);

	env_lock();
	/* check parameter_buffer malloc is successful and memset */
	if( parameter_buffer == NULL ) {
		IMP_LOG_ERR(TAG, "malloc parameter_buffer error \n");
		ret = -1;
		goto write_out;
	}
	memset(parameter_buffer, 0x00, 256);

	strcpy(file_buffer, dst);

	/* find the token in file_buffer, if don't find, create it */
	sprintf(token_buffer, "%s]", token);
	if( strlen(file_buffer) < strlen(token_buffer) )
		temp_start_p = NULL;
	else
		temp_start_p = strstr(file_buffer, token_buffer);
	if( temp_start_p == NULL ) {
		if(value) {
			sprintf(parameter_buffer, "[%s];%s=%s;", token, parameter, value);
			strcat(dst, parameter_buffer);
		}
		goto file_write_out;
	}

	/* if token already created, copy token data to temp buffer */
	temp_end_p = strchr(temp_start_p, '[');
	if( temp_end_p == NULL ) {
		temp_end_p = file_buffer + strlen(file_buffer);
		temp_buffer = (char *)malloc(strlen(temp_start_p)+1);
		if( temp_buffer == NULL ) {
			IMP_LOG_ERR(TAG, "ERROR: temp_buffer malloc failed %s, %d\n", __func__, __LINE__);
			ret = -1;
			goto file_write_out;
		}
		memset(temp_buffer, 0x00, strlen(temp_start_p)+1);
		strcpy(temp_buffer, temp_start_p);
	} else {
		temp_buffer = (char *)malloc(temp_end_p-temp_start_p+1);
		if( temp_buffer == NULL ) {
			IMP_LOG_ERR(TAG, "ERROR: temp_buffer malloc failed %s, %d\n", __func__, __LINE__);
			ret = -1;
			goto file_write_out;
		}
		memset(temp_buffer, 0x00, temp_end_p-temp_start_p+1);
		strncpy(temp_buffer, temp_start_p, temp_end_p-temp_start_p);
	}

	/* find the parameter in temp_buffer */
	while(1) {
		/* if find but don't parameter we need, continue search */
		if (parameter_p != NULL)
			parameter_p = strstr(parameter_p+strlen(parameter), parameter);
		else /* first serch */
			parameter_p = strstr(temp_buffer, parameter);
		/* already find */
		if( (parameter_p != NULL) && (*(parameter_p+strlen(parameter)) == '=')) {
			parameter_end_p = strstr(parameter_p, ";");
			if( parameter_end_p == NULL ) {
				IMP_LOG_ERR(TAG, "parameter_end_p is NULL\n");
			}
			memset(dst, 0x0, dst_size);
			strncpy(dst, file_buffer, (temp_start_p+(parameter_p-temp_buffer)-file_buffer));
			if(value) {
				sprintf(parameter_buffer, "%s=%s", parameter, value);
				strcat(dst, parameter_buffer);
				strcat(dst, (char *)(temp_start_p+(parameter_end_p-temp_buffer)));
			} else {
				strcat(dst, (char *)(temp_start_p+((parameter_end_p+1)-temp_buffer)));
			}
			break;
		} else if(parameter_p != NULL){ /* find but not we need */
			continue;
		}else { /* not find */
			memset(dst, 0x0, dst_size);
			strncpy(dst, file_buffer, temp_end_p-file_buffer);
			if(value) {
				sprintf(parameter_buffer, "%s=%s;", parameter, value);
				strcat(dst, parameter_buffer);
			}
			strcat(dst, temp_end_p);
			break;
		}
	}

	free(temp_buffer);
file_write_out:
	free(parameter_buffer);
write_out:

	env_unlock();
	return ret;
}

#define CMD_LINE "/tmp/cmdline"
int cmdline_get_env(char *token, char *param, char *result)
{
	char buf[1024] = "";
	int ret;
	char *p = NULL;

	FILE *fb = fopen(CMD_LINE, "r");
	if(fb == NULL) {
		IMP_LOG_ERR(TAG,  "%s open file (%s) error\n", __func__, CMD_LINE);
		return -1;
	}

	ret = fread(buf, 1, sizeof(buf), fb);
	if(ret <= 0) {
		IMP_LOG_ERR(TAG,  "%s fread (%s) error\n", __func__, CMD_LINE);
		fclose(fb);
		return -1;
	}

	fclose(fb);

	p = strstr(buf, "senv;");
	if(p == NULL) {
		IMP_LOG_ERR(TAG,  "%s fread (%s) error\n", __func__, CMD_LINE);
		return -1;
	}

	return read_env(p+5, token, param, result);
}

int cmdline_set_env(char *token, char *param, char *value)
{
	char cmdline[1024] = "";
	char buf[1024] = "";
	char env[1024] = "";
	char *ps = NULL, *pe = NULL;
	int ret = 0;

	FILE *fb = fopen(CMD_LINE, "r");
	if(fb == NULL) {
		IMP_LOG_ERR(TAG,  "%s open file (%s) error\n", __func__, CMD_LINE);
		return -1;
	}

	ret = fread(cmdline, 1, sizeof(cmdline), fb);
	if(ret <= 0) {
		IMP_LOG_ERR(TAG,  "%s fread (%s) error\n", __func__, CMD_LINE);
		fclose(fb);
		return -1;
	}
	fclose(fb);

	ps = strstr(cmdline, "senv;");
	if(ps == NULL) {
		IMP_LOG_ERR(TAG,  "%s fread (%s) error\n", __func__, CMD_LINE);
		return -1;
	}

	pe = strstr(cmdline, "eenv");
	if(pe == NULL) {
		IMP_LOG_ERR(TAG,  "%s fread (%s) error\n", __func__, CMD_LINE);
		return -1;
	}

	strncpy(buf, ps+5, (pe-(ps+5)));
	write_env(buf, sizeof(buf), token, param, value);
	sprintf(env, "senv;%seenv;", buf);

	fb = fopen(CMD_LINE, "w+");
	if(fb == NULL) {
		IMP_LOG_ERR(TAG,  "%s open file (%s) error\n", __func__, CMD_LINE);
		return -1;
	}

	ret = fwrite(env, 1, strlen(env), fb);
	if(ret <= 0) {
		IMP_LOG_ERR(TAG,  "%s fread (%s) error\n", __func__, CMD_LINE);
		fclose(fb);
		return -1;
	}

	fclose(fb);

	return 0;
}
